package com.xcity.game.skill;

import java.text.MessageFormat;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.game.combat.attr.CombatAttributeType;
import com.xcity.game.common.Cause;
import com.xcity.game.common.MessageConst;
import com.xcity.game.event.GameEvents;
import com.xcity.game.skill.template.SkillLevelUpTemplate;
import com.xcity.game.skill.v2.DefaultSkillV2;
import com.xcity.game.skill.v2.SkillManagerV2;
import com.xcity.pomelo.PomeloRoute;
import com.xcity.pomelo.request.SkillActivateRequest;
import com.xcity.pomelo.request.SkillInfoRequest;
import com.xcity.pomelo.request.SkillInfoV2Request;
import com.xcity.pomelo.request.SkillLevelUpV2Request;
import com.xcity.pomelo.request.SkillListRequest;
import com.xcity.pomelo.request.SkillListV2Request;
import com.xcity.pomelo.request.SkillPhaseLearnRequest;
import com.xcity.pomelo.response.HintResponse;
import com.xcity.pomelo.response.SkillInfoV2Response;
import com.xcity.pomelo.response.SkillLevelUpV2Response;
import com.xcity.pomelo.response.SkillListV2Response;

import naga.x.App;
import naga.x.event.Event;
import naga.x.event.EventListener;
import naga.x.net.Session;
import naga.x.net.annotation.OPHandler;
import naga.x.net.impl.pomelo.annotation.PomeloOP;
import naga.x.service.Service;
import naga.x.service.ServiceException;

@OPHandler
public class SkillService implements Service, EventListener {

//	public static final int SKILL_BOOK_ID_FOR_FRESHER = 71000; // 20170331 removed, no use
//	public static SkillTemplate playerDefaultSkillTemplate;
	public static final Logger LOG = LoggerFactory.getLogger(SkillService.class);
	
	@Override
	public void startup() throws ServiceException {
//		playerDefaultSkillTemplate = App.getApp().getServiceManager().get(TemplateService.class).get(SkillTemplate.class, GameStaticConfig.playerDefaultSkillId);
//		if (playerDefaultSkillTemplate == null) {
//			throw new ServiceException("player's default skill not found: " + GameStaticConfig.playerDefaultSkillId);
//		}
		App.getApp().getEventManager().register(this);
	}

	@Override
	public void shutdown() throws ServiceException {
	}

	@Override
	public String getId() {
		return getClass().getName();
	}
	
	@Override
	public int[] getEventTypes() {
//		return new int[] { GameEvents.EVENT_PLAYER_LOGIN, GameEvents.EVENT_PLAYER_LOGOUT };
		return new int[] {
				GameEvents.EVENT_PLAYER_STAR_LVL_UP,
				GameEvents.EVENT_EMPLOYEE_STAR_UP,
		};
	}

	@Override
	public void handleEvent(Event event) {
//		Player player = event.getParameter();
//		switch (event.getType()) {
//			case GameEvents.EVENT_PLAYER_LOGIN:
//				player.getSkillManager().playerLogin();
//				break;
//			case GameEvents.EVENT_PLAYER_LOGOUT:
//				player.getSkillManager().playerLogout();
//				break;
//		}
		switch (event.getType()) {
			case GameEvents.EVENT_PLAYER_STAR_LVL_UP:
				Player player = event.getParameter(0);
				int starLvl = event.getParameter(2);
				tryUnlockSkill(player.getSkillManager(), starLvl);
				break;
			case GameEvents.EVENT_EMPLOYEE_STAR_UP:
				Employee employee = event.getParameter(1);
				tryUnlockSkill(employee.getSkillManager(), employee.getStarLvl());
				break;
		}
	}
	
	private void tryUnlockSkill(SkillManagerV2 manager, int starLvl) {
		List<DefaultSkillV2> passives = manager.getPassives();
		for (int i = 0, size = passives.size(); i < size; i++) {
			DefaultSkillV2 skill = passives.get(i);
			if (!skill.isUnlocked()) {
				if (starLvl >= skill.getUnlockStarLvl()) {
					skill.setUnlocked((byte) 1);
				} else {
					// 后面技能一定未达到解锁要求
					break;
				}
			}
		}
	}
	
	@PomeloOP(PomeloRoute.SKILL_LIST)
	protected void requestSkillList(Session session, SkillListRequest req) {
//		Player player = session.getClient();
//		List<PlayerSkill> skills = player.getSkillManager().getSkills();
//		if (skills != null) { // 20170331 removed, no use
//			for (int i = 0; i < skills.size(); i++) {
//				skills.get(i).update(true, Cause.MANUAL);
//			}
//		}
//		session.send(new SkillListResponse(req.getSerial(), skills));
	}
	
	@PomeloOP(PomeloRoute.SKILL_INFO)
	protected void requestSkillInfo(Session session, SkillInfoRequest req) {
//		Player player = session.getClient();
//		PlayerSkill skill = player.getSkillManager().getSkill(req.getId());
//		if (skill == null) {
//			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_NOT_FOUND));
//			return;
//		}
//		skill.update(true, Cause.MANUAL); // 20170331 removed, no use
//		session.send(new SkillInfoResponse(req.getSerial(), skill));
	}
	
	@PomeloOP(PomeloRoute.SKILL_ACTIVATE)
	protected void requestActivateSkill(Session session, SkillActivateRequest req) {
		// 20170331 removed, no use
//		if (req.getId() <= 0) {
//			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_NOT_FOUND));
//			return;
//		}
//		Player player = session.getClient();
//		try {
//			PlayerSkill skill = req.getOp() != 0 ? player.getSkillManager().activate(req.getId()) : player.getSkillManager().unactivate();
//			session.send(new SimpleSkillResponse(req.getSerial(), skill));
//		} catch (SkillException e) {
//			session.send(new HintResponse(req.getSerial(), e.getMessage()));
//		}
		
		session.send(new HintResponse(req.getSerial(), MessageConst.FUNC_NOT_OPEN));
	}

	@PomeloOP(PomeloRoute.SKILL_PHASE_LEARN)
	protected void requestPhaseLearn(Session session, SkillPhaseLearnRequest req) {
		// 20170331 removed, no use
//		if (req.getId() <= 0) {
//			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_NOT_FOUND));
//			return;
//		}
//		Player player = session.getClient();
//		PlayerSkill skill = player.getSkillManager().getSkill(req.getId());
//		if (skill == null) {
//			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_NOT_FOUND));
//			return;
//		}
//		try {
//			if (req.getOp() != 0) {
//				skill.startPhaseLearn(TimeUpdater.getInstance().now(), Cause.MANUAL);
//			} else {
//				skill.pausePhaseLearn(Cause.MANUAL);
//			}
//			session.send(new SimpleSkillResponse(req.getSerial(), skill));
//		} catch (SkillException e) {
//			session.send(new HintResponse(req.getSerial(), e.getMessage()));
//		}
		
		session.send(new HintResponse(req.getSerial(), MessageConst.FUNC_NOT_OPEN));
	}
	
	@PomeloOP(PomeloRoute.SKILL_LIST_V2)
	protected void requestList2(Session session, SkillListV2Request req) {
		Player player = session.getClient();
		long unitId = req.id;
		if (unitId == -1 || unitId == player.getId()) {
			session.send(new SkillListV2Response(req.getSerial(), player, unitId, player.getSkillManager()));
			return;
		}
		Employee employee = player.getEmployees().get(unitId);
		if (employee == null) {
			session.send(new HintResponse(req.getSerial(), MessageConst.EMPLOYEE_NOT_EXIST));
			return;
		}
		session.send(new SkillListV2Response(req.getSerial(), player, unitId, employee.getSkillManager()));
	}
	
	@PomeloOP(PomeloRoute.SKILL_V2)
	protected void requestSkill2(Session session, SkillInfoV2Request req) {
		Player player = session.getClient();
		DefaultSkillV2 skill = SkillUtils.find(player, req.id, req.skillId);
		if (skill == null) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_NOT_FOUND));
			return;
		}
		session.send(new SkillInfoV2Response(req.getSerial(), req.id, skill));
	}
	
	@PomeloOP(PomeloRoute.SKILL_LVL_UP)
	protected void requestLvlUp2(Session session, SkillLevelUpV2Request req) {
		Player player = session.getClient();
		DefaultSkillV2 skill = SkillUtils.find(player, req.id, req.skillId);
		if (skill == null) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_NOT_FOUND));
			return;
		}
		if (!skill.isUnlocked()) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_LOCKED));
			return;
		}
		if (skill.getLevel() >= skill.getTemplate().getMaxLevel()) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_LEVEL_MAXED));
			return;
		}
		if (skill.getLevel() >= skill.getVm().getOwner().getLevel()) {
			session.send(new HintResponse(req.getSerial(),
					MessageFormat.format(MessageConst.SKILL_LEVEL_CAN_NOT_EXCEED_OWNER,
							req.id == -1 || req.id == player.getId() ? MessageConst.UNIT_PLAYER : MessageConst.UNIT_EMPLOYEE)));
			return;
		}
		SkillLevelUpTemplate template = skill.getTemplate().getUpLvlTemplate(skill.getLevel() + 1);
		if (template == null) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_LEVEL_MAXED));
			return;
		}
		int gold = template.getGold();
		int points = template.getPoints();
		if (gold <= 0 && points <= 0) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SYSTEM_ERROR));
			return;
		}
		if (!player.isGoldEnough(gold)) {
			session.send(new HintResponse(req.getSerial(), MessageConst.GOLD_NOT_ENOUGH));
			return;
		}
		if (player.getSkillPoints() < points) {
			session.send(new HintResponse(req.getSerial(), MessageConst.SKILL_POINTS_NOT_ENOUGH));
			return;
		}
		player.costGold(gold, Cause.SKILL_LEVEL_UP);
		player.decSkillPoints(points, Cause.SKILL_LEVEL_UP);
		skill.addLevel(1, Cause.MANUAL);
		session.send(new SkillLevelUpV2Response(req.getSerial(), req.id, skill));
		CombatAttributeType[] enhancedTypes = skill.getEnhanceTypes();
		if (enhancedTypes != null) {
			int mask = 0;
			for (CombatAttributeType type : enhancedTypes) {
				mask |= 1 << type.ordinal();
			}
			skill.getVm().getOwner().fireAttributesChanged(mask);
		}
		LOG.info("[SKILL LVLUP]ID[{}]UNIT[{}]SKILL[{}]LVL[{}]CAUSE[{}]", player.getId(), req.id, skill.getId(), skill.getLevel(), Cause.MANUAL);
	}
	
}
